#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
混合优化器 - MCP决策优化服务改进版

基于电子产品质量控制测试的分析结果，实现智能算法选择和混合优化策略：
1. 小规模问题使用穷举法保证全局最优
2. 大规模问题使用智能算法
3. 提供解质量验证和算法性能对比
4. 增强结果可解释性
"""

import numpy as np
import itertools
import time
from typing import Dict, List, Any, Optional, Tuple, Union
from dataclasses import dataclass
from enum import Enum
import logging
from copy import deepcopy

# 导入现有模型
try:
    from .models import (
        OptimizationProblem, DecisionVariable, ObjectiveFunction, 
        VariableType, OptimizationType, AlgorithmType
    )
    from .multi_objective_engine import MultiObjectiveEngine
except ImportError:
    from models import (
        OptimizationProblem, DecisionVariable, ObjectiveFunction,
        VariableType, OptimizationType, AlgorithmType
    )
    from multi_objective_engine import MultiObjectiveEngine


class OptimizationStrategy(Enum):
    """优化策略枚举"""
    EXHAUSTIVE = "exhaustive"  # 穷举法
    INTELLIGENT = "intelligent"  # 智能算法
    HYBRID = "hybrid"  # 混合策略
    AUTO = "auto"  # 自动选择


@dataclass
class OptimizationConfig:
    """优化配置"""
    strategy: OptimizationStrategy = OptimizationStrategy.AUTO
    max_variables_for_exhaustive: int = 6  # 穷举法的最大变量数
    max_combinations_for_exhaustive: int = 1000  # 穷举法的最大组合数
    enable_verification: bool = True  # 是否启用解验证
    enable_comparison: bool = True  # 是否启用算法对比
    timeout_seconds: int = 300  # 超时时间


@dataclass
class SolutionQuality:
    """解质量评估"""
    is_optimal: bool
    optimality_gap: float
    confidence_level: float
    verification_method: str
    quality_score: float  # 0-1之间的质量评分


@dataclass
class OptimizationResult:
    """优化结果"""
    problem_name: str
    strategy_used: OptimizationStrategy
    algorithm_used: str
    best_solution: Dict[str, Any]
    best_objective_value: float
    all_solutions: List[Dict[str, Any]]
    execution_time: float
    quality_assessment: SolutionQuality
    convergence_info: Dict[str, Any]
    metadata: Dict[str, Any]


class ExhaustiveSearchEngine:
    """穷举搜索引擎"""
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
    
    def can_solve(self, problem: OptimizationProblem, config: OptimizationConfig) -> bool:
        """判断是否可以使用穷举法求解"""
        if len(problem.variables) > config.max_variables_for_exhaustive:
            return False
        
        # 计算总组合数
        total_combinations = 1
        for var in problem.variables:
            if var.variable_type == VariableType.BINARY:
                total_combinations *= 2
            elif var.variable_type == VariableType.INTEGER:
                range_size = int(var.upper_bound - var.lower_bound) + 1
                total_combinations *= range_size
            else:
                # 连续变量需要离散化，这里假设离散化为10个点
                total_combinations *= 10
            
            if total_combinations > config.max_combinations_for_exhaustive:
                return False
        
        return True
    
    def solve(self, problem: OptimizationProblem, objective_function=None) -> OptimizationResult:
        """使用穷举法求解"""
        start_time = time.time()
        
        # 生成所有可能的解
        all_solutions = self._generate_all_solutions(problem)
        
        # 评估所有解
        evaluated_solutions = []
        for solution in all_solutions:
            obj_value = self._evaluate_solution(solution, problem, objective_function)
            evaluated_solutions.append({
                'solution': solution,
                'objective_value': obj_value
            })
        
        # 找到最优解
        best_solution_data = max(evaluated_solutions, key=lambda x: x['objective_value'])
        
        execution_time = time.time() - start_time
        
        # 质量评估（穷举法保证全局最优）
        quality = SolutionQuality(
            is_optimal=True,
            optimality_gap=0.0,
            confidence_level=1.0,
            verification_method="exhaustive_search",
            quality_score=1.0
        )
        
        return OptimizationResult(
            problem_name=problem.name,
            strategy_used=OptimizationStrategy.EXHAUSTIVE,
            algorithm_used="exhaustive_search",
            best_solution=best_solution_data['solution'],
            best_objective_value=best_solution_data['objective_value'],
            all_solutions=evaluated_solutions,
            execution_time=execution_time,
            quality_assessment=quality,
            convergence_info={
                'converged': True,
                'iterations': len(all_solutions),
                'total_evaluations': len(all_solutions)
            },
            metadata={
                'total_combinations': len(all_solutions),
                'search_space_coverage': 1.0
            }
        )
    
    def _generate_all_solutions(self, problem: OptimizationProblem) -> List[Dict[str, Any]]:
        """生成所有可能的解"""
        variable_ranges = []
        
        for var in problem.variables:
            if var.variable_type == VariableType.BINARY:
                variable_ranges.append([0, 1])
            elif var.variable_type == VariableType.INTEGER:
                start = int(var.lower_bound or 0)
                end = int(var.upper_bound or 10)
                variable_ranges.append(list(range(start, end + 1)))
            else:  # CONTINUOUS
                # 离散化连续变量
                start = var.lower_bound or 0
                end = var.upper_bound or 1
                variable_ranges.append(np.linspace(start, end, 10).tolist())
        
        # 生成所有组合
        all_combinations = list(itertools.product(*variable_ranges))
        
        # 转换为解字典
        solutions = []
        for combination in all_combinations:
            solution = {}
            for i, var in enumerate(problem.variables):
                solution[var.name] = combination[i]
            solutions.append(solution)
        
        return solutions
    
    def _evaluate_solution(self, solution: Dict[str, Any], problem: OptimizationProblem, 
                          objective_function=None) -> float:
        """评估解的目标函数值"""
        if objective_function:
            return objective_function(solution)
        
        # 默认评估方式（简化）
        if problem.objectives:
            # 使用第一个目标函数
            obj = problem.objectives[0]
            # 简化计算：假设目标函数是变量值的加权和
            value = sum(solution.values())
            return value if obj.optimization_type == OptimizationType.MAXIMIZE else -value
        
        return sum(solution.values())


class HybridOptimizer:
    """混合优化器 - 智能选择最佳算法"""
    
    def __init__(self, config: OptimizationConfig = None):
        self.config = config or OptimizationConfig()
        self.exhaustive_engine = ExhaustiveSearchEngine()
        self.intelligent_engine = MultiObjectiveEngine()
        self.logger = logging.getLogger(__name__)
    
    def optimize(self, problem: OptimizationProblem, 
                objective_function=None, **kwargs) -> OptimizationResult:
        """执行优化"""
        # 选择优化策略
        strategy = self._select_strategy(problem)
        
        self.logger.info(f"为问题 '{problem.name}' 选择策略: {strategy.value}")
        
        if strategy == OptimizationStrategy.EXHAUSTIVE:
            result = self._solve_with_exhaustive(problem, objective_function)
        elif strategy == OptimizationStrategy.INTELLIGENT:
            result = self._solve_with_intelligent(problem, objective_function, **kwargs)
        else:  # HYBRID
            result = self._solve_with_hybrid(problem, objective_function, **kwargs)
        
        # 后处理：验证和分析
        if self.config.enable_verification:
            result = self._verify_solution(result, problem, objective_function)
        
        return result
    
    def _select_strategy(self, problem: OptimizationProblem) -> OptimizationStrategy:
        """智能选择优化策略"""
        if self.config.strategy != OptimizationStrategy.AUTO:
            return self.config.strategy
        
        # 自动选择策略
        if self.exhaustive_engine.can_solve(problem, self.config):
            return OptimizationStrategy.EXHAUSTIVE
        else:
            return OptimizationStrategy.INTELLIGENT
    
    def _solve_with_exhaustive(self, problem: OptimizationProblem, 
                              objective_function=None) -> OptimizationResult:
        """使用穷举法求解"""
        return self.exhaustive_engine.solve(problem, objective_function)
    
    def _solve_with_intelligent(self, problem: OptimizationProblem, 
                               objective_function=None, **kwargs) -> OptimizationResult:
        """使用智能算法求解"""
        start_time = time.time()
        
        # 这里应该调用现有的智能算法
        # 简化实现：随机搜索
        best_solution = None
        best_value = float('-inf')
        all_solutions = []
        
        num_iterations = kwargs.get('num_iterations', 1000)
        
        for i in range(num_iterations):
            solution = self._generate_random_solution(problem)
            value = self._evaluate_solution(solution, problem, objective_function)
            
            all_solutions.append({
                'solution': solution,
                'objective_value': value
            })
            
            if value > best_value:
                best_value = value
                best_solution = solution
        
        execution_time = time.time() - start_time
        
        # 估计解质量
        quality = self._estimate_solution_quality(best_value, all_solutions)
        
        return OptimizationResult(
            problem_name=problem.name,
            strategy_used=OptimizationStrategy.INTELLIGENT,
            algorithm_used="random_search",
            best_solution=best_solution,
            best_objective_value=best_value,
            all_solutions=all_solutions,
            execution_time=execution_time,
            quality_assessment=quality,
            convergence_info={
                'converged': True,
                'iterations': num_iterations,
                'total_evaluations': num_iterations
            },
            metadata={
                'algorithm_type': 'random_search',
                'search_space_coverage': min(1.0, num_iterations / 10000)
            }
        )
    
    def _solve_with_hybrid(self, problem: OptimizationProblem, 
                          objective_function=None, **kwargs) -> OptimizationResult:
        """使用混合策略求解"""
        # 先尝试穷举法，如果不可行则使用智能算法
        if self.exhaustive_engine.can_solve(problem, self.config):
            return self._solve_with_exhaustive(problem, objective_function)
        else:
            return self._solve_with_intelligent(problem, objective_function, **kwargs)
    
    def _generate_random_solution(self, problem: OptimizationProblem) -> Dict[str, Any]:
        """生成随机解"""
        solution = {}
        for var in problem.variables:
            if var.variable_type == VariableType.BINARY:
                solution[var.name] = np.random.choice([0, 1])
            elif var.variable_type == VariableType.INTEGER:
                lb = int(var.lower_bound or 0)
                ub = int(var.upper_bound or 10)
                solution[var.name] = np.random.randint(lb, ub + 1)
            else:  # CONTINUOUS
                lb = var.lower_bound or 0
                ub = var.upper_bound or 1
                solution[var.name] = np.random.uniform(lb, ub)
        return solution
    
    def _evaluate_solution(self, solution: Dict[str, Any], problem: OptimizationProblem,
                          objective_function=None) -> float:
        """评估解"""
        if objective_function:
            return objective_function(solution)
        
        # 默认评估
        if problem.objectives:
            obj = problem.objectives[0]
            value = sum(solution.values())
            return value if obj.optimization_type == OptimizationType.MAXIMIZE else -value
        
        return sum(solution.values())
    
    def _estimate_solution_quality(self, best_value: float, 
                                  all_solutions: List[Dict]) -> SolutionQuality:
        """估计解质量"""
        all_values = [sol['objective_value'] for sol in all_solutions]
        
        # 计算质量指标
        value_range = max(all_values) - min(all_values)
        if value_range > 0:
            relative_position = (best_value - min(all_values)) / value_range
        else:
            relative_position = 1.0
        
        # 估计最优性差距（基于搜索历史）
        improvement_rate = 0.0
        if len(all_values) > 100:
            recent_best = max(all_values[-100:])
            early_best = max(all_values[:100])
            if early_best > 0:
                improvement_rate = (recent_best - early_best) / abs(early_best)
        
        # 估计置信水平
        confidence = min(0.95, 0.5 + relative_position * 0.4 + min(0.1, improvement_rate))
        
        return SolutionQuality(
            is_optimal=False,  # 智能算法不保证全局最优
            optimality_gap=max(0.0, 1.0 - relative_position),
            confidence_level=confidence,
            verification_method="statistical_estimation",
            quality_score=relative_position
        )
    
    def _verify_solution(self, result: OptimizationResult, problem: OptimizationProblem,
                        objective_function=None) -> OptimizationResult:
        """验证解的质量"""
        if result.strategy_used == OptimizationStrategy.EXHAUSTIVE:
            # 穷举法已经是最优解，无需验证
            return result
        
        # 对智能算法的结果进行验证
        if self.exhaustive_engine.can_solve(problem, self.config):
            # 可以用穷举法验证
            exact_result = self.exhaustive_engine.solve(problem, objective_function)
            
            # 比较结果
            gap = abs(exact_result.best_objective_value - result.best_objective_value)
            relative_gap = gap / abs(exact_result.best_objective_value) if exact_result.best_objective_value != 0 else 0
            
            # 更新质量评估
            result.quality_assessment.optimality_gap = relative_gap
            result.quality_assessment.is_optimal = (relative_gap < 1e-6)
            result.quality_assessment.verification_method = "exhaustive_verification"
            result.quality_assessment.confidence_level = 1.0
            
            # 添加验证信息到元数据
            result.metadata['verification'] = {
                'exact_optimal_value': exact_result.best_objective_value,
                'found_optimal_value': result.best_objective_value,
                'absolute_gap': gap,
                'relative_gap': relative_gap,
                'is_globally_optimal': result.quality_assessment.is_optimal
            }
        
        return result
    
    def compare_algorithms(self, problem: OptimizationProblem, 
                          objective_function=None) -> Dict[str, Any]:
        """比较不同算法的性能"""
        if not self.config.enable_comparison:
            return {"message": "算法比较功能已禁用"}
        
        results = {}
        
        # 尝试穷举法
        if self.exhaustive_engine.can_solve(problem, self.config):
            try:
                exhaustive_result = self._solve_with_exhaustive(problem, objective_function)
                results['exhaustive'] = {
                    'objective_value': exhaustive_result.best_objective_value,
                    'execution_time': exhaustive_result.execution_time,
                    'quality_score': exhaustive_result.quality_assessment.quality_score,
                    'is_optimal': exhaustive_result.quality_assessment.is_optimal
                }
            except Exception as e:
                results['exhaustive'] = {'error': str(e)}
        
        # 尝试智能算法
        try:
            intelligent_result = self._solve_with_intelligent(problem, objective_function)
            results['intelligent'] = {
                'objective_value': intelligent_result.best_objective_value,
                'execution_time': intelligent_result.execution_time,
                'quality_score': intelligent_result.quality_assessment.quality_score,
                'is_optimal': intelligent_result.quality_assessment.is_optimal
            }
        except Exception as e:
            results['intelligent'] = {'error': str(e)}
        
        # 生成比较报告
        comparison_report = self._generate_comparison_report(results)
        
        return {
            'problem_name': problem.name,
            'algorithm_results': results,
            'comparison_report': comparison_report,
            'recommendation': self._recommend_algorithm(results)
        }
    
    def _generate_comparison_report(self, results: Dict[str, Any]) -> Dict[str, Any]:
        """生成算法比较报告"""
        report = {
            'summary': {},
            'performance_metrics': {},
            'trade_offs': []
        }
        
        valid_results = {k: v for k, v in results.items() if 'error' not in v}
        
        if len(valid_results) >= 2:
            # 性能对比
            best_objective = max(r['objective_value'] for r in valid_results.values())
            fastest_time = min(r['execution_time'] for r in valid_results.values())
            
            for alg_name, result in valid_results.items():
                obj_ratio = result['objective_value'] / best_objective if best_objective != 0 else 1
                time_ratio = result['execution_time'] / fastest_time if fastest_time != 0 else 1
                
                report['performance_metrics'][alg_name] = {
                    'objective_quality_ratio': obj_ratio,
                    'time_efficiency_ratio': 1 / time_ratio,
                    'overall_score': (obj_ratio + 1/time_ratio) / 2
                }
        
        return report
    
    def _recommend_algorithm(self, results: Dict[str, Any]) -> Dict[str, Any]:
        """推荐最佳算法"""
        valid_results = {k: v for k, v in results.items() if 'error' not in v}
        
        if not valid_results:
            return {'algorithm': 'none', 'reason': '所有算法都失败了'}
        
        # 如果穷举法可用且成功，优先推荐
        if 'exhaustive' in valid_results and valid_results['exhaustive']['is_optimal']:
            return {
                'algorithm': 'exhaustive',
                'reason': '穷举法保证全局最优解，且计算时间可接受'
            }
        
        # 否则根据综合性能推荐
        best_alg = max(valid_results.keys(), 
                      key=lambda k: valid_results[k]['quality_score'])
        
        return {
            'algorithm': best_alg,
            'reason': f'{best_alg}算法在当前问题上表现最佳'
        }


# 使用示例和测试函数
def create_electronic_product_problem() -> OptimizationProblem:
    """创建电子产品质量控制问题"""
    variables = [
        DecisionVariable(
            name="x1_inspect",
            variable_type=VariableType.BINARY,
            description="是否检测零配件1"
        ),
        DecisionVariable(
            name="x2_inspect", 
            variable_type=VariableType.BINARY,
            description="是否检测零配件2"
        ),
        DecisionVariable(
            name="y_inspect",
            variable_type=VariableType.BINARY, 
            description="是否检测成品"
        ),
        DecisionVariable(
            name="z_disassemble",
            variable_type=VariableType.BINARY,
            description="是否拆解不合格品"
        )
    ]
    
    objectives = [
        ObjectiveFunction(
            name="profit",
            expression="maximize_profit",
            optimization_type=OptimizationType.MAXIMIZE,
            description="最大化利润"
        )
    ]
    
    return OptimizationProblem(
        name="electronic_product_quality_control",
        variables=variables,
        objectives=objectives,
        description="电子产品质量控制决策优化"
    )


def electronic_product_objective(solution: Dict[str, Any]) -> float:
    """电子产品问题的目标函数"""
    x1 = solution.get('x1_inspect', 0)
    x2 = solution.get('x2_inspect', 0) 
    y = solution.get('y_inspect', 0)
    z = solution.get('z_disassemble', 0)
    
    # 简化的利润计算（基于测试案例）
    revenue = 56  # 销售收入
    cost = 4 + 18 + 6  # 基础成本
    
    # 检测成本
    inspection_cost = x1 * 2 + x2 * 3 + y * 3
    
    # 拆解成本
    disassembly_cost = z * 5
    
    # 质量收益（简化模型）
    quality_benefit = x1 * 5 + x2 * 8 + y * 4
    
    profit = revenue - cost - inspection_cost - disassembly_cost + quality_benefit
    return profit


if __name__ == "__main__":
    # 测试混合优化器
    problem = create_electronic_product_problem()
    
    # 创建优化器
    config = OptimizationConfig(
        strategy=OptimizationStrategy.AUTO,
        enable_verification=True,
        enable_comparison=True
    )
    optimizer = HybridOptimizer(config)
    
    # 执行优化
    result = optimizer.optimize(problem, electronic_product_objective)
    
    print(f"问题: {result.problem_name}")
    print(f"使用策略: {result.strategy_used.value}")
    print(f"最优解: {result.best_solution}")
    print(f"最优值: {result.best_objective_value:.2f}")
    print(f"执行时间: {result.execution_time:.4f}秒")
    print(f"解质量: {result.quality_assessment.quality_score:.3f}")
    print(f"是否最优: {result.quality_assessment.is_optimal}")
    
    # 算法比较
    print("\n=== 算法比较 ===")
    comparison = optimizer.compare_algorithms(problem, electronic_product_objective)
    print(f"推荐算法: {comparison['recommendation']['algorithm']}")
    print(f"推荐理由: {comparison['recommendation']['reason']}")